package Socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/*
    聊天室服务端
 */
public class Server {
    private ServerSocket serverSocket;
    private List<PrintWriter> allout = new ArrayList<>();
    public Server() {
        try {
            System.out.println("正在启动服务端...");
            serverSocket = new ServerSocket(8088);
            System.out.println("成功！");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void Start() {
        try {
            while(true) {
                System.out.println("等待客户连接中...");
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端连接成功");
                //启动一个线程和客户端实现交互
                clientHandler client = new clientHandler(socket);
                Thread r = new Thread(client);
                r.start();
            }
            } catch(IOException e){
                throw new RuntimeException(e);
            }
        }


    public static void main(String[] args) {
        Server server = new Server();
        server.Start();
    }


    /**
     * 指定客户端进行交互
     */
    private class clientHandler implements Runnable{
      private Socket socket;
      private String host;//记录客户端的地址信息
        public  clientHandler(Socket socket){
            this.socket = socket;
            //通过getInetAddress获取远端计算机地址，并且以字符串形式返回
            host = socket.getInetAddress().getHostAddress();
        }
        @Override
        public void run() {
            PrintWriter pw = null;
            try{
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);
                //通过socket获取输出流，发送数据给用户端
                OutputStream os = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(os,StandardCharsets.UTF_8);
                BufferedWriter bw = new BufferedWriter(osw);
                pw = new PrintWriter(bw,true);
                //将输出流存入共享集合用于广播信息
                synchronized (allout){
                    allout.add(pw);
                }
                //当客户端上线，广播通知所有用户该用户上线
                sentmessage(host+"上线了，在线人数为"+allout.size());


                String line;
                System.out.println("说话：");
                while ((line = br.readLine()) != null) {
                    sentmessage(host+"说:"+line);
                }

            }catch (Exception e){
                e.printStackTrace();
            }finally {
                //处理客户端断开连接的操作
                //1.将客户端的输出流从allout删除
                synchronized (allout) {
                    allout.remove(pw);
                }

                try {

                    //2.关闭socket流
                    socket.close();

                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //当客户端下线，广播通知所有用户该用户下线
                sentmessage(host+"下线了，在线人数为"+allout.size());
            }
        }

        /**
         * 将消息发送个所有客户端
         * @param message 消息值
         */
        private void sentmessage(String message){
                System.out.println(message);
                //将消息发送给所有客户端
                synchronized(allout){
                for(PrintWriter p: allout){
                    p.println(host+"说:"+message);
            }
            }
        }
    }
}
